package com.tbit.uqbike.compalint.service.base;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tbit.common.config.OssDefaultConfig;
import com.tbit.uqbike.compalint.enums.ComplaintStatusEnum;
import com.tbit.uqbike.compalint.enums.PlatformEnum;
import com.tbit.uqbike.compalint.param.*;
import com.tbit.uqbike.compalint.table.ComplaintDO;
import com.tbit.uqbike.compalint.table.ComplaintHistoryDO;
import com.tbit.uqbike.compalint.vo.ComplaintHistoryVO;
import com.tbit.uqbike.compalint.vo.ComplaintVO;
import com.tbit.uqbike.object.pojo.OssConfig;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.common.entity.view.PageResult;
import com.tbit.uqbike.compalint.mapper.ComplaintHistoryMapper;
import com.tbit.uqbike.compalint.mapper.ComplaintMapper;
import com.tbit.uqbike.webmanager.util.BeanUtils;
import com.tbit.uqbike.webmanager.util.UserContextUtil;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 客诉服务层
 *
 * @author <a href="mailto:zhang.zhiliang@tbit.com.cn">Zhang ZhiLiang</a>
 * @version 1.0
 * @see <a href="http://adsl1.tbit.com.cn:21490/pages/viewpage.action?pageId=82182491">订单号规范</a>
 * @since 2025/2/14
 */
@Slf4j
public abstract class AbstractComplaintService {
    public static final String COMPLAINANT = "投诉人";
    public static final String SYSTEM = "系统";

    protected final ComplaintMapper complaintMapper;
    protected final ComplaintHistoryMapper complaintHistoryMapper;
    protected final OssDefaultConfig ossDefaultConfig;

    protected AbstractComplaintService(ComplaintMapper complaintMapper,
                                       ComplaintHistoryMapper complaintHistoryMapper, OssDefaultConfig ossDefaultConfig) {
        this.complaintMapper = complaintMapper;
        this.complaintHistoryMapper = complaintHistoryMapper;
        this.ossDefaultConfig = ossDefaultConfig;
    }

    /**
     * 列表查询条件构造
     *
     * @param param
     * @return
     */
    private LambdaQueryWrapper<ComplaintDO> getComplaintDOQueryWrapper(ComplaintPageParam param) {
        return new LambdaQueryWrapper<ComplaintDO>()
                .eq(Objects.nonNull(param.getComplaintId()), ComplaintDO::getComplaintId, param.getComplaintId())
                .eq(Objects.nonNull(param.getPhone()), ComplaintDO::getPhone, param.getPhone())
                .eq(Objects.nonNull(param.getOrderNO()), ComplaintDO::getOrderNO, param.getOrderNO())
                .eq(Objects.nonNull(param.getBrandId()), ComplaintDO::getBrandId, param.getBrandId())
                .eq(Objects.nonNull(param.getOperatorPhone()), ComplaintDO::getOperatorPhone, param.getOperatorPhone())
                .between((Objects.nonNull(param.getStartTime()) && Objects.nonNull(param.getEndTime()))
                        , ComplaintDO::getComplaintTime, param.getStartTime(), param.getEndTime())
                .eq((Objects.nonNull(param.getPlatform()) && !Objects.equals(param.getPlatform(), PlatformEnum.ALL.getCode())), ComplaintDO::getPlatform, param.getPlatform())
                .eq((Objects.nonNull(param.getStatus()) && !Objects.equals(param.getStatus(), ComplaintStatusEnum.ALL.getCode())), ComplaintDO::getStatus, param.getStatus())
                .orderByDesc(ComplaintDO::getComplaintTime);
    }

    /**
     * 查询客诉列表分页
     *
     * @param param
     * @return
     */
    public PageResult<ComplaintVO> page(ComplaintPageParam param) {
        IPage<ComplaintDO> page = new Page<>(param.getPageNO(), param.getPageSize());
        IPage<ComplaintDO> pageResult = complaintMapper.selectPage(page, getComplaintDOQueryWrapper(param));
        List<ComplaintVO> res = pageResult.getRecords().stream().map(x -> {
            ComplaintVO complaintVO = BeanUtils.copyProperties(x, ComplaintVO.class);
            complaintVO.format();
            return complaintVO;
        }).collect(Collectors.toList());
        return new PageResult<>((int) pageResult.getCurrent(), (int) pageResult.getSize(), pageResult.getTotal(), (int) pageResult.getPages(), res);
    }

    /**
     * 查询列表
     *
     * @param param
     * @return
     */
    public List<ComplaintVO> list(ComplaintPageParam param) {
        List<ComplaintDO> complaintDOList = complaintMapper.selectList(getComplaintDOQueryWrapper(param));
        return complaintDOList.stream().map(x -> {
            ComplaintVO complaintVO = BeanUtils.copyProperties(x, ComplaintVO.class);
            complaintVO.format();
            return complaintVO;
        }).collect(Collectors.toList());
    }

    /**
     * 协商历史
     * 拉取三方平台协商历史接口 ， 增量更新到数据库 ， 并返回结果
     *
     * @param param 客诉协商历史入参
     * @return 该条客诉的协商历史
     */
    public List<ComplaintHistoryVO> history(ComplaintHistoryParam param) {
        List<ComplaintHistoryDO> complaintHistoryDOListFromApi = getHistoryDetailApi(param);
        List<ComplaintHistoryDO> complaintHistoryDOListFromDB = complaintHistoryMapper.selectList(new LambdaQueryWrapper<ComplaintHistoryDO>()
                .eq(ComplaintHistoryDO::getComplaintId, param.getComplaintId())
                .orderByAsc(ComplaintHistoryDO::getSendTime)
        );
        Set<String> existUuidSet = complaintHistoryDOListFromDB.stream().map(ComplaintHistoryDO::getUuid).collect(Collectors.toSet());

        // 外部平台故障，使用数据库中的数据 降级处理
        if (Objects.isNull(complaintHistoryDOListFromApi) || complaintHistoryDOListFromApi.isEmpty()) {
            complaintHistoryDOListFromApi = complaintHistoryDOListFromDB;
        }else {
            // 拉取到数据，筛选增量数据插入
            List<ComplaintHistoryDO> insertList = complaintHistoryDOListFromApi.stream().filter(x -> !existUuidSet.contains(x.getUuid())).collect(Collectors.toList());
            complaintHistoryMapper.insertBatch(insertList);
        }
        return complaintHistoryDOListFromApi.stream().map(x -> {
            ComplaintHistoryVO complaintHistoryVO = BeanUtils.copyProperties(x, ComplaintHistoryVO.class);
            complaintHistoryVO.format();
            return complaintHistoryVO;
        }).sorted(Comparator.comparing(ComplaintHistoryVO::getSendTime)).collect(Collectors.toList());
    }

    /**
     * 校验当前客诉条目的状态 ， 并更新到数据库
     * 三方平台状态是已完成，则提示用户
     *
     * @param param 客诉状态校验参数
     * @return 是否成功
     */
    public Boolean verify(ComplaintVerifyParam param) {
        ComplaintStatusEnum complaintStatusEnum = getDetailApi(param);
        if (Objects.isNull(complaintStatusEnum)){
            return true;
        }
        return complaintMapper.update(new LambdaUpdateWrapper<ComplaintDO>()
                .set(ComplaintDO::getStatus, complaintStatusEnum.getCode())
                .eq(ComplaintDO::getComplaintId, param.getComplaintId())
        ) > 0;
    }

    /**
     * 获取阿里云oss配置
     *
     * @return
     */
    public OssConfig getOssConfig() {
        /**阿里云配置*/
        return new OssConfig(ossDefaultConfig.getEndpoint(),
                ossDefaultConfig.getAccessKeyId(),
                ossDefaultConfig.getAccessKeySecret(), "gx-res");
    }

    /**
     * 平台回复客诉
     *
     * @param param 回复客诉参数
     * @return 是否成功
     */
    public Boolean response(ComplaintResponseParam param) {
        if (responseApi(param)) {
            LoginInfo loginInfo = (LoginInfo) UserContextUtil.get(UserContextUtil.USER_KEY);
            return complaintMapper.update(new LambdaUpdateWrapper<ComplaintDO>()
                    .set(ComplaintDO::getStatus, ComplaintStatusEnum.PROCESSING.getCode())
                    .set(ComplaintDO::getOperator,loginInfo.getName())
                    .set(ComplaintDO::getOperatorPhone,loginInfo.getPhone())
                    .eq(ComplaintDO::getComplaintId, param.getComplaintId())) > 0;
        }
        return false;
    }

    /**
     * 平台主动拉取客诉
     * @param param 拉取客诉参数
     * @return 是否成功
     */
    public Boolean complaintPull(ComplaintPullParam param) {
        try {
            List<ComplaintDO> complaintDOListFromApi = pullComplaintApi(param);
            log.info("品牌{}拉取{}平台客诉参数{},拉取数量{}",param.getBrandId(),PlatformEnum.getByCode(param.getPlatform()).getName(), JSON.toJSONString(param), complaintDOListFromApi.size());
            List<ComplaintDO> complaintDOListFromDB = complaintMapper.selectList(new LambdaQueryWrapper<ComplaintDO>().select(ComplaintDO::getComplaintId)
                    .eq(ComplaintDO::getBrandId, param.getBrandId()).eq(ComplaintDO::getPlatform,param.getPlatform()));
            Set<String> existComplaintIdSet = complaintDOListFromDB.stream().map(ComplaintDO::getComplaintId).collect(Collectors.toSet());
            // 筛选增量数据
            List<ComplaintDO> insertList = complaintDOListFromApi.stream().filter(x -> !existComplaintIdSet.contains(x.getComplaintId())).collect(Collectors.toList());
            return complaintMapper.insertBatch(insertList);
        }catch (Exception e){
            log.error("客诉拉取参数{}发生错误",JSON.toJSONString(param),e);
        }
        return false;
    }

    /**
     * 查询数据库中品牌当天当前时刻的客诉条数
     * @param brandId 品牌id
     * @return 客诉条数
     */
    public Long getSize(Integer brandId){
        return complaintMapper.selectCount(new LambdaQueryWrapper<ComplaintDO>()
                .eq(ComplaintDO::getBrandId,brandId)
                .likeRight(ComplaintDO::getComplaintTime, LocalDate.now().toString())
        );
    }

    /**
     * 回复用户客诉留言
     *
     * @param param 回复用户客诉留言
     * @return 是否成功
     */
    public abstract Boolean responseApi(ComplaintResponseParam param);

    /**
     * 拉取三方客诉详情
     *
     * @param param 客诉状态拉取参数
     * @return
     */
    public abstract ComplaintStatusEnum getDetailApi(ComplaintVerifyParam param);

    /**
     * 拉取三方客诉协商历史
     *
     * @param param 客诉协商历史查询参数
     * @return
     */
    public abstract List<ComplaintHistoryDO> getHistoryDetailApi(ComplaintHistoryParam param);

    /**
     * 客诉反馈处理完成
     *
     * @param param 客诉反馈处理完成参数
     * @return 是否成功
     */
    public abstract Boolean completeApi(ComplaintCompleteParam param);

    /**
     * 客诉拉取Api
     * @param param 客诉拉取参数
     * @return 是否成功
     */
    public abstract List<ComplaintDO> pullComplaintApi(ComplaintPullParam param);

}
